﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Qianke.Core.Common
{
    /// <summary>
    /// 数据转换辅助类
    /// 作者：张朝南
    /// </summary>
    public static class JObjectHelper
    {
        public static T SaveToVal<T>(this JToken obj, T devVal)
        {
            return obj.SafeToString().ToVal(devVal);
        }

        /// <summary>
        /// 安全返回字符串 如果为不存在 返回 string.Empty
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string SafeToString(this JToken obj, string defVal = "")
        {
            return obj == null ? defVal : obj.ToString();
        }

        /// <summary>
        /// 安全返回Byte变体
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static byte? ToByte(this JToken obj)
        {
            return obj.SafeToString().ToByte();
        }

        /// <summary>
        /// 安全返回整形变体
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static int? ToInt(this JToken obj)
        {
            return obj.SafeToString().ToInt();
        }

        /// <summary>
        /// 安全返回长整形变体
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static long? ToInt64(this JToken obj)
        {
            return obj.SafeToString().ToInt64();
        }

        /// <summary>
        /// 安全返回十进制数变体
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static decimal? ToDecimal(this JToken obj)
        {
            return obj.SafeToString().ToDecimal();
        }

        /// <summary>
        /// 安全返回时间类型
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static DateTime? ToDateTime(this JToken obj)
        {
            return obj.SafeToString().ToDateTime();
        }

        /// <summary>
        /// 安全返回双经度小数类型
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static double? ToDouble(this JToken obj)
        {
            return obj.SafeToString().ToDouble();
        }

        /// <summary>
        /// 安全返回Byte
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static byte ToByte(this JToken obj, byte defVal)
        {
            return obj.ToByte() ?? defVal;
        }

        /// <summary>
        /// 安全返回整数 
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defVal">默认值</param>
        /// <returns></returns>
        public static int ToInt(this JToken obj, int defVal)
        {
            return obj.ToInt() ?? defVal;
        }

        /// <summary>
        /// 安全返回长整形
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defVal">默认值</param>
        /// <returns></returns>
        public static long ToInt64(this JToken obj, long defVal)
        {
            return obj.ToInt64() ?? defVal;
        }

        /// <summary>
        /// 安全返回十进制数
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defVal">默认值</param>
        /// <returns></returns>
        public static decimal ToDecimal(this JToken obj, decimal defVal)
        {
            return obj.ToDecimal() ?? defVal;
        }

        /// <summary>
        /// 安全返回时间类型变体
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defVal">默认值</param>
        /// <returns></returns>
        public static DateTime ToDateTime(this JToken obj, DateTime defVal)
        {
            return obj.ToDateTime() ?? defVal;
        }

        /// <summary>
        /// 安全返回双经度小鼠类型变体
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defVal">默认值</param>
        /// <returns></returns>
        public static double ToDouble(this JToken obj, double defVal)
        {
            return obj.ToDouble() ?? defVal;
        }

        public static TimeSpan? ToTimeSpan(this JToken obj)
        {
            return obj.SafeToString().ToTimeSpan();
        }

        public static TimeSpan ToTimeSpan(this JToken obj, TimeSpan defaultTimeSpan)
        {
            return obj.ToTimeSpan() ?? defaultTimeSpan;
        }

        public static Guid? ToGuid(this JToken obj)
        {
            Guid defGuid = Guid.Empty;
            return Guid.TryParse(obj.SafeToString(), out defGuid) ? defGuid : (Guid?)null;
        }

        public static Guid ToGuid(this JToken obj, Guid defVal)
        {
            return obj.ToGuid() ?? defVal;
        }

        public static string ToJson<TModel>(this TModel model)
        {
            var longConvert = new JsonNumberConverter();
            return Newtonsoft.Json.JsonConvert.SerializeObject(model, longConvert);
        }

        public static TModel ToObject<TModel>(this string strObject)
        {
            return (TModel)strObject.ToObject(typeof(TModel));
        }

        public static object ToObject(this string strObject, Type objType)
        {
            if (string.IsNullOrEmpty(strObject)) return Activator.CreateInstance(objType);
            var settings = new Newtonsoft.Json.JsonSerializerSettings();
            settings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore;
            settings.Error += (s, e) => { e.ErrorContext.Handled = true; };
            return Newtonsoft.Json.JsonConvert.DeserializeObject(strObject, objType, settings);
        }
    }



    public class JsonNumberOfNumberConverter : JsonNumberConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (value == null)
            {
                writer.WriteNull();
            }
            else
            {
                var objectType = value.GetType();
                var typeCode = Type.GetTypeCode(objectType.Name.Equals("Nullable`1") ? objectType.GetGenericArguments().First() : objectType);
                switch (typeCode)
                {
                    case TypeCode.Int16:
                    case TypeCode.Byte:
                    case TypeCode.Int32:
                    case TypeCode.Decimal:
                    case TypeCode.Double:
                    case TypeCode.UInt16:
                    case TypeCode.UInt32:
                    case TypeCode.UInt64:
                    case TypeCode.Boolean:
                    case TypeCode.Int64:
                        writer.WriteValue(value);
                        break;
                    case TypeCode.DateTime:
                        writer.WriteValue(((DateTime)value).ToString("yyyy-MM-dd HH:mm:ss"));
                        break;
                    case TypeCode.String:
                        var str = value as string;
                        if (str == null)
                            str = string.Empty;
                        writer.WriteValue(str);
                        break;
                    default:
                        writer.WriteValue(value.ToString());
                        break;
                }
            }
        }
    }
}
